<?php
/*
 * Copyright (c) Taras Kudla, Cretsu Pavlo 2010
 */
 
# registration types
define("_REGISTER_IMMEDIATELY",0);
define("_REGISTER_VIA_EMAIL",1);
define("_REGISTER_VIA_ADMINISTRATOR",2);
 
class mod_users extends gModule {
	
	# maximum number of incorrect auth tryies
	private $MaxAuthFails = 5;
	# default registration type
	private $RegistrationType  = _REGISTER_IMMEDIATELY;
	# password recovery applications table
	private $Passwordrecoverytable = "mod_users_passwdrecovery";
	# registration applications table
	private $Applicationstable = "mod_users_regapplications";
	# users additional information
	private $Usersadditionaltable = "mod_users_additional";
	
	public function init(){
	
	}
	
	# top enter/exit panel
	public function panel(){
		$entered = $this->api->user->CheckUser();
		$admin = ( $this->api->user->GetUserGroup() == 1 )?true:false;
		
		return $this->api->view->template("panel", array(
			"entered"=>(int)$entered,
			"username" => $this->api->user->GetUserName(),
			"admin" => $admin
		));
		
	}
	
	# system entering
	public function enter(){
        	
        	$this->api->cms->addway("users-enter",null,$this->lang->get("e1"));
        	if (isset($_GET["exit"])){
            		$this->api->user->SysExit();
            		return $this->api->redirect();
          	}
       		if ($this->api->user->CheckUser()){
            		return $this->api->message($this->i18n->get("e8"));
          	}
		/*
		 * Checking for number of auth fails
	 	 */
		$fail=false;	
		$useCaptcha=false;
		if($this->api->session->exists("authfails")){
			$fails=$this->api->session->get("authfails");
			if($fails>2){
				$useCaptcha=true;
			}		
			if($fails>=$this->MaxAuthFails){				
				return $this->api->message($this->i18n->get("e9"));
			}
		}
		if($useCaptcha==true || ( isset($fails) && $fails>1 ) ){
			$CaptchaModule=$this->api->cms->callmodule("captcha");
		}
       		if ( $this->api->checkPOST("ulogin","upasswd","Submit") ){	
                      	$remember = (isset($_POST["remember"])) ? true : false;
 	    		$login = $this->api->escapeString($_POST["ulogin"]);
	   		$passwd = $_POST["upasswd"];
			if($useCaptcha){
	    			$check=isset($_POST["check"])?$_POST["check"]:false;  	
	    		}
	    		if($useCaptcha && ( !$check || !$CaptchaModule->check($check)) ){
			    	$fail=true;
	    			print $this->api->message($this->i18n->get("e10"));
	    		} else	
	    		if(!$this->checkEmail($login)){
	    			$fail=true;	    	
	    			print $this->api->message($this->i18n->get("e11"));
	    		} else {	
            			$r = $this->api->user->SysAuth($login, $passwd, $remember,true);
            			if ($r == false){
              				$fail=true;   
                			print $this->api->message($this->i18n->get("e12"));
              			}
            			else {
                			return $this->api->cms->redirect();
              			}
            			}
          	}
       		if($fail){
		/*
                 * Incrementing number of authorization fails
                 */
         	if($this->api->session->exists("authfails")){
      			$authfails=$this->api->session->get("authfails");
              		$authfails++;
              		$this->api->session->set("authfails",$authfails);	
           	} else {
              		$this->api->session->set("authfails",0);
		}         
        	}
    		$captchaimage = (isset($fails) && $fails>1)?$CaptchaModule->getImageURL():0;
		#Getting template
		return $this->api->view->template("enter",array("imageurl"=>$captchaimage));
	}
	
	public function quit(){
		$this->api->user->sysexit();
		$this->api->redirect();
	}
	
	public function register(){
	
	}
	
	public function passwdrecovery(){
		$this->api->cms->AddWay("users-passwdrecovery",null,$this->lang->get("p1") );
		# Checking for previous recovery action
		if($this->api->session->exists("PasswordRecovery")){
			return $this->api->message($this->i18n->get("p5"));
		}
		# Checking if data entered
		$this->api->cms->LoadModule("captcha",$CaptchaModule);
		if($this->api->checkPOST("email","check","PasswordSubmit")){
			list($email)=$this->api->escapePOST("email");
			if(!$this->CheckEmail($email)){
				print $this->api->message($this->i18n->get("p6"));
			} else if(!$CaptchaModule->check($_POST["check"])){
				print $this->api->message($this->i18n->get("p7"));
			} else if (!$this->api->dbo->select("users","id","where email='$email' limit 1 offset 0",_RESULT_BOOL)){
				print $this->api->message($this->i18n->get("p8"));
			} else if($this->api->dbo->select($this->Passwordrecoverytable,"hash","where email='$email' limit 1 offset 0",_RESULT_BOOL)){
				print $this->api->message($this->i18n->get("p9"));
			} else {
				# creating new record about password remind
				$this->api->session->set("PasswordRecovery",true);				 
				$this->api->log->write("try to recovery a password for email '$email' ",_LOG_NOTICE,_AUTH_LOG);
				$hash=md5($email.microtime(true).rand(0,99));
				$this->api->dbo->insert($this->Passwordrecoverytable,array("hash"=>$hash,"email"=>$email,"createdate"=>date("U"),"newpassword"=>$this->api->encodeString($this->genpassword())));
				# sending a message via email
				$template=$this->api->view->template("emails/newpassword_".$this->api->language());	
				# Finishing
				return $this->api->message($this->i18n->get("p10"));
			}
		}
		# building main password recovery form
		return $this->api->view->template("passwordrecovery",array("imageurl"=>$CaptchaModule->getImageUrl()));
	}
	
	/*
	 * Some usefull functions
	 */
	# checking if email is correct
	private function checkEmail($email){
		return preg_match("/^[^@]+@[^@]+$/i", $email, $trash);	
	}
	# password generator
	private function genpassword($length = 9, $strength = 9){
        	$vowels     = 'aeuy';
       		$consonants = 'bdghjmnpqrstvz';
        	if ($strength > 1){
            		$consonants .= 'BDGHJLMNPQRSTVWXZ';
          	}
        	if ($strength > 2){
           		$vowels .= "AEUY";
          	}
        	if ($strength > 4){
            		$consonants .= '23456789';
          	}
        	if ($strength > 8){
			$consonants .= '@#$%';
		}
		$password = '';
		$alt      = time() % 2;
		for ($i = 0; $i < $length; $i++){
			if ($alt == 1){
				$password .= $consonants[(rand() % strlen($consonants))];
				$alt = 0;
			} else {
				$password .= $vowels[(rand() % strlen($vowels))];
				$alt = 1;
			}
		}
		return $password;
	}
	/*
	 * Administration
	 */	
	
	# creating a new group
	public function newgroup(){
		if($this->api->checkPOST("gname","Submit")){
			$gname=$this->api->escapeString($_POST["gname"]);
			$_=$this->api->dbo->insert("groups",array("name"=>$gname,"access"=>"","createdate"=>date("Y-m-d H:i:s")));
			$this->api->log->write("new group '".$gname."' created");
			if($_){
				return $this->api->message($this->i18n->get("g4"));
			}
			else {
				return $this->api->error($this->i18n->get("g5"));
			}
		}
		return $this->api->view->template("addgroup");	
	}
        
        #output list of groups
        public function groups(){ 
		# getting groups list
		$Query=$this->api->dbo->select("groups","id,name,createdate",null);
		return $this->api->view->template("groups",array("data"=>&$Query));
	}

        # group name/access editing
	public function editgroup(){
		if(!isset($_GET["group"]) || !is_numeric($_GET["group"]))return null;
		$id=$this->api->escapeString($_GET["group"]);
		if( $this->api->checkPOST("Submit","accessbox","groupname") && is_array($_POST["accessbox"])){
			# trying to reset group access options
			$chaccess = implode(",",$_POST["accessbox"]);
			$newname = $this->api->escapeString($_POST["groupname"]);
			$oldname = $this->api->dbo->select("groups","name","where id='$id' limit 1 offset 0",_RESULT_SINGLE);
			if( strlen($newname)>1 && $newname!=$oldname){
				$this->api->dbo->update("groups","set name='$newname' where id='$id' ");
			}
			$this->api->dbo->update("groups","set access='$chaccess' where id='$id'");
			$this->api->log->write("Changing access options for group $id");
		}
		$Query=	$this->api->dbo->select("groups","id,name,access"," where id='".$id."' limit 1 offset 0",_RESULT_ROW);
		if(count ($Query)<3){
			return $this->api->error($this->i18n->get("g14"));
		}
		$access=$this->api->dbo->select("functions","hash,id,alias"," where guest!='1' order by alias");
		# getting data for access managing
		$groupaccess = explode(",",$Query["access"]);
		return $this->api->view->template("editgroup",array("name"=>$Query["name"],"id"=>$id,"access"=>&$access,"groupaccess"=>$groupaccess));
	}

	# removing group and all its users
	public function deletegroup(){
		print "Somebody wants to delete a group";
	}

	# creating a new user
	public function newuser(){
		if($this->api->checkPOST("firstname","lastname","email","password1","password2","group")){
			list($firstname,$lastname,$email,$password1,$password2,$group)=$this->api->escapePOST("firstname","lastname","email","password1","password2","group");
			if(strlen($firstname)<3){
				print $this->api->message($this->i18n->get("c3"));
			}else if(!preg_match("/^[^@]+@[^@]+\.[^@]+$/i",$email,$trash) ) {
				print $this->api->message($this->i18n->get("c4"));
			} else if ( strcmp($password1,$password2)!=0 ) {
				print $this->api->message($this->i18n->get("c5"));
			} else if( $this->api->dbo->select("users","id","where email='".$email."' limit 1 offset 0",_RESULT_BOOL) ) {
				print $this->api->message($this->i18n->get("c6"));
			}
			else {
				$this->api->dbo->insert("users",array(
				"firstname"=>trim($firstname),
				"lastname"=>trim($lastname),
				"passwd"=>$this->api->encodeString($password1),
				"email"=>trim($email),
				"groupid"=>(int)$group,
				"status"=>1,
				"lastip"=>$this->api->user->GetMyIP(),
				"lastdate"=>date("Y-m-d H:i:s"),
				"createdate"=>date("Y-m-d H:i:s"),
				"hash"=>$this->api->encodeString($email.$password1)
				));
				$this->api->log->write("New user $email was created");
				print $this->api->message($this->i18n->get("c7"));
			}
		}
		return $this->api->view->template("newuser",array("groups"=>$this->api->dbo->select("groups","id,name")));
	}

	public function users(){
 		# getting groups list
		$user_query=$this->api->dbo->select("users","id,firstname,createdate",null);
		return $this->api->view->template("users",array("data"=>&$user_query));
	}
	
	# registration applications managing
	public function applications(){
			
		$Applications = $this->api->dbo->select($this->Applicationstable,"*");
		return $this->api->view->template("applications",array("data"=>&$Applications));
	}
	
	# module configuration method
	public function options(){
		
		if( $this->api->checkPOST("Submit","regtype","maxauth","group", "r_nickname","r_cellphone","r_workphone","r_homephone","r_fax","r_country","r_city","r_address","r_postindex","r_companyname","r_companydep", "r_companyjob","r_companysize","r_workaddress","r_sex","r_education") ){
		
			$this->api->options->set("registrationtype",(int)$_POST["regtype"]);
			$this->api->options->set("maxauthfails",(int)$_POST["maxauth"]);
			$this->api->options->set("defaultusergroup",(int)$_POST["group"]);
			$this->api->options->set("usetermsofuse", isset($_POST["usetermsofuse"])?true:false);
			$this->api->options->set("r_nickname",(int)$_POST["r_nickname"]);
			$this->api->options->set("r_cellphone",(int)$_POST["r_cellphone"]);	
			$this->api->options->set("r_workphone",(int)$_POST["r_workphone"]);
			$this->api->options->set("r_homephone",(int)$_POST["r_homephone"]);
			$this->api->options->set("r_fax",(int)$_POST["r_fax"]);	
			$this->api->options->set("r_country",(int)$_POST["r_country"]);
			$this->api->options->set("r_city",(int)$_POST["r_city"]);
			$this->api->options->set("r_address",(int)$_POST["r_address"]);
			$this->api->options->set("r_postindex",(int)$_POST["r_postindex"]);
			$this->api->options->set("r_companyname",(int)$_POST["r_companyname"]);
			$this->api->options->set("r_companydep",(int)$_POST["r_companydep"]);
			$this->api->options->set("r_companyjob",(int)$_POST["r_companyjob"]);
			$this->api->options->set("r_companysize",(int)$_POST["r_companysize"]);
			$this->api->options->set("r_workaddress",(int)$_POST["r_workaddress"]);
			$this->api->options->set("r_sex",(int)$_POST["r_sex"]);
			$this->api->options->set("r_education",(int)$_POST["r_education"]);
		}
		$data = $this->api->options->get();
		if( !$data){
			return $this->api->error(null,"Cannot read 'users' options data");
		}		
		return $this->api->view->template("options",array("data"=>$data,"groups"=>$this->api->dbo->select("groups","id,name")) );
	}
	 
	public function install(){
		/*
		 *  Creating basic tables
		 */
		# password recovery table 
		$table = new sqltable($this->Passwordrecoverytable);
		$table->addfield("hash",_FIELD_CHAR);
		$table->addfield("email",_FIELD_CHAR);
		$table->addfield("newpassword",_FIELD_CHAR);
		$table->addkey("hash",_KEY_PRIMARY);
		$this->api->dbo->createtable($table);
		unset($table);
		
		# users additional information
		$table = new sqltable($this->Usersadditionaltable);
		$table->addfield("userid",_FIELD_INT);
		$table->addfield("nickname",_FIELD_CHAR);
		$table->addfield("birthday",_FIELD_DATE);
		$table->addfield("cellphone",_FIELD_CHAR);
		$table->addfield("workphone",_FIELD_CHAR);
		$table->addfield("homephone",_FIELD_CHAR);
		$table->addfield("fax",_FIELD_CHAR);
		$table->addfield("companyname",_FIELD_CHAR);
		$table->addfield("companydep",_FIELD_CHAR);
		$table->addfield("companyjob",_FIELD_CHAR);
		$table->addfield("companysize",_FIELD_CHAR);
		$table->addfield("country",_FIELD_CHAR);
		$table->addfield("city",_FIELD_CHAR);
		$table->addfield("address",_FIELD_CHAR);
		$table->addfield("workaddress",_FIELD_CHAR);
		$table->addfield("sex",_FIELD_CHAR);
		$table->addfield("postindex",_FIELD_CHAR);
		$table->addfield("education",_FIELD_CHAR);
		$table->addfield("image",_FIELD_INT);
		$table->addfield("image_middle",_FIELD_INT);
		$table->addfield("image_small",_FIELD_INT);
		$table->addkey(_KEY_PRIMARY,"userid");
		$this->api->dbo->createtable($table);
		unset($table);
		
		# applications table
		$table= new sqltable($this->Applicationstable);
		$table->addfield("id",_FIELD_INTAUTO);
		$table->addfield("email",_FIELD_CHAR);
		$table->addfield("passwd",_FIELD_CHAR);
		$table->addfield("firstname",_FIELD_CHAR);
		$table->addfield("lastname",_FIELD_CHAR);
		$table->addfield("nickname",_FIELD_CHAR);
		$table->addfield("birthday",_FIELD_DATE);
		$table->addfield("cellphone",_FIELD_CHAR);
		$table->addfield("workphone",_FIELD_CHAR);
		$table->addfield("homephone",_FIELD_CHAR);
		$table->addfield("fax",_FIELD_CHAR);
		$table->addfield("companyname",_FIELD_CHAR);
		$table->addfield("companydep",_FIELD_CHAR);
		$table->addfield("companyjob",_FIELD_CHAR);
		$table->addfield("companysize",_FIELD_CHAR);
		$table->addfield("country",_FIELD_CHAR);
		$table->addfield("city",_FIELD_CHAR);
		$table->addfield("address",_FIELD_CHAR);
		$table->addfield("workaddress",_FIELD_CHAR);
		$table->addfield("sex",_FIELD_CHAR);
		$table->addfield("postindex",_FIELD_CHAR);
		$table->addfield("education",_FIELD_CHAR);
		$table->addfield("appcreated",_FIELD_DATETIME);
		$this->api->dbo->createtable($table);
		unset($table);
		
		/*
		 * Setting up all users additional information properties
		 */
		$this->api->options->set("r_birthday",false);
		$this->api->options->set("r_cellphone",false);
		$this->api->options->set("r_workphone",false);
		$this->api->options->set("r_homephone",false);
		$this->api->options->set("r_fax",false);
		$this->api->options->set("r_companyname",false);
		$this->api->options->set("r_companydep",false);
		$this->api->options->set("r_companyjob",false);
		$this->api->options->set("r_companysize",false);
		$this->api->options->set("r_country",false);
		$this->api->options->set("r_city",false);
		$this->api->options->set("r_address",false);
		$this->api->options->set("r_workaddress",false);
		$this->api->options->set("r_nickname",false);
		$this->api->options->set("r_sex",false);
		$this->api->options->set("r_postindex",false);
		$this->api->options->set("r_education",false);
		/*
		 * Setting up configuration information
		 */
		$this->api->options->set("registrationtype",_REGISTER_IMMEDIATELY);
		$this->api->options->set("maxauthfails",5);
		$this->api->options->set("usetermsofuse",true);
		$this->api->options->set("defaultusergroup",2);
	}
	
	public function uninstall(){
	
	}
}
